
package nsga;

public class IndividuoQAP implements Cloneable, Individuo
{
    private int[] localidades;
    private int[] edificios;
    private int length;
    private int cantidadDigitos;
    private double[] fitness;
    private double fitnessAlgoritmo;
    
    public IndividuoQAP(int length)
    {
        this.length=length;
        localidades=new int[this.length];
        edificios=new int[this.length];
        for(int i=0;i<this.length;i++)
        {
            localidades[i]=-1;
            edificios[i]=-1;
        }
        cantidadDigitos=(int)Math.pow(10, String.valueOf(this.length).length());
    }
    
    public static IndividuoQAP getIndividuoGeneradoAleatoriamente(int length)
    {
        IndividuoQAP individuoQAP=new IndividuoQAP(length);
        for(int i=0;i<individuoQAP.length;i++)
        {
            do
            {
                int rand;
                do
                {
                    rand=(int)(Math.random()*individuoQAP.cantidadDigitos);
                }
                while(rand>=individuoQAP.length);
                if(individuoQAP.setEdificioToLocalidad(i, rand))
                {
                    break;
                }
            }
            while(true);
        }
        return individuoQAP;
    }
    
    public double[] getFitness()
    {
        return fitness.clone();
    }
    
    public void setFitness(double[] fitness)
    {
        this.fitness=fitness;
    }
    
    public double getFitnessAlgoritmo()
    {
        return fitnessAlgoritmo;
    }

    public void setFitnessAlgoritmo(double fitnessAlgoritmo)
    {
        this.fitnessAlgoritmo = fitnessAlgoritmo;
    }
    
    public int[] getLocalidades()
    {
        return localidades.clone();
    }
    
    public void mutar()
    {
        int rand1;
        do
        {
            rand1=(int)(Math.random()*cantidadDigitos);
        }
        while(rand1>=length);
        int rand2;
        do
        {
            rand2=(int)(Math.random()*cantidadDigitos);
        }
        while((rand2>=this.length)||(rand1==rand2));
        int tmp=localidades[rand1];
        localidades[rand1]=localidades[rand2];
        localidades[rand2]=tmp;
        edificios[tmp]=rand2;
        edificios[localidades[rand1]]=rand1;
    }

    public boolean setEdificioToLocalidad(int edificio, int localidad)
    {
        if(edificios[edificio]==-1)
        {
            if(localidades[localidad]==-1)
            {
                localidades[localidad]=edificio;
                edificios[edificio]=localidad;
                return true;
            }
            else
            {
                return false;
            }
        }
        else
        {
            return false;
        }
    }
    
    public Individuo clone()
    {
        IndividuoQAP individuoQAP=null;
        try
        {
            individuoQAP=(IndividuoQAP)super.clone();
        }
        catch(CloneNotSupportedException cloneNotSupportedException)
        {
        }
        individuoQAP.localidades=localidades.clone();
        individuoQAP.edificios=edificios.clone();
        individuoQAP.fitness=fitness.clone();
        return individuoQAP;
    }
    
    public static void isIndividuoValido(IndividuoQAP individuoQAP)
    {
        int[] prueba=new int[individuoQAP.length];
        for(int i=0;i<prueba.length;i++)
        {
            if(prueba[individuoQAP.localidades[i]]>0)
            {
                throw new Error("Individuo QAP invalido!!!");
            }
            else
            {
                prueba[individuoQAP.localidades[i]]++;
            }
        }
        for(int i=0;i<prueba.length;i++)
        {
            if(prueba[i]!=1)
            {
                throw new Error("Individuo QAP invalido!!!");
            }
            else
            {
                prueba[i]=0;
            }
        }
        for(int i=0;i<prueba.length;i++)
        {
            if(prueba[individuoQAP.edificios[i]]>0)
            {
                throw new Error("Individuo QAP invalido!!!");
            }
            else
            {
                prueba[individuoQAP.edificios[i]]++;
            }
        }
        for(int i=0;i<prueba.length;i++)
        {
            if(prueba[i]!=1)
            {
                throw new Error("Individuo QAP invalido!!!");
            }
        }
    }

}